package com.sd.repay.transfer.bank;

import com.alibaba.fastjson.JSONObject;
import com.sd.repay.channel.cj.util.EncryptUtil;
import com.sd.repay.channel.cj.util.SignUtil;
import com.sd.repay.common.CommonResult;
import com.sd.repay.pojo.TransferChannelInfo;
import com.sd.repay.pojo.TransferOrder;
import com.sd.repay.transfer.TransferChannelCache;
import com.sd.repay.utils.HttpUtil;
import com.sd.repay.utils.JsonUtil;
import com.sd.repay.utils.StringUtil;
import okhttp3.Response;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.TreeMap;

/**
 * 畅捷 - 代付
 *
 * @author
 */
@Service
public class CJPayService extends BaseRepayService {

    private Logger log = LoggerFactory.getLogger(CJPayService.class);

    private String channelName = "畅捷";

    @Override
    public CommonResult channelCheck(TransferOrder order) {
        CommonResult result = new CommonResult();

        String bankName = order.getInBankName();
        if (StringUtil.isBlank(bankName)) {
            result.setStatus(2);
            result.setMsg("缺少银行名称");
            return result;
        }
        
        String busiCode = order.getBak2();
        if (StringUtil.isBlank(busiCode)) {
            result.setStatus(2);
            result.setMsg("bak2缺少支付业务类型");
            return result;
        }
        
        if (!busiCode.equals("400") && !busiCode.equals("402")) {
        	result.setStatus(2);
            result.setMsg("支付业务类型错误");
            return result;
        }
        result.setStatus(1);
        return result;
    }

    @Override
    public void transferOrder(TransferOrder order) {
        log.info(channelName.concat("代付[{}]执行开始"), order.toJsonString());
        String status = "";
        String resultCode = "";
        String resultMsg = "";
        String orderNo = "";
        String acqOrderNo = "";
        String token = "";
        try {
            orderNo = getOrderNo(order);
            TransferChannelInfo channelInfo = (TransferChannelInfo) TransferChannelCache.getChannel(order.getOutPayBank() + order.getOutAccNo());

            BigDecimal amount = order.getAmount();
            amount = amount.multiply(oneHundred);

            String outAccNo = order.getOutAccNo();
            String key = channelInfo.getEncryptionKey();
            String url = channelInfo.getPayUrl();
            String busiCode = order.getBak2();


            CommonResult result = entryCardConfirm(orderNo, outAccNo, key, url);
            if (result.getStatus() == 2) {
                order.setStatus("2");
                order.setSubResultCode("Token is null");
                order.setSubResultMsg(result.getMsg());
                return;
            }

            token = result.getMsg();
            String zqMerNo = order.getAcqMerNo();
            String accName = order.getInAccName();
            String accNo = order.getInAccNo();
            String bankName = order.getInBankName();
            String bankNo = order.getInBankNo();
            String accNoEncryp = EncryptUtil.desEncrypt(accNo, key);
            TreeMap<String, Object> signParams = new TreeMap<String, Object>();
            signParams.put("token", token);                                            //令牌，明文令牌
            signParams.put("spCode", outAccNo);                                        //服务商编号
            signParams.put("reqFlowNo", orderNo);                                    //请求流水号
            signParams.put("merchantCode", zqMerNo);                                //商户号
            signParams.put("walletType", Integer.valueOf(busiCode));                //钱包类型 402、快捷支付T1钱包 400、快捷支付D0钱包
            signParams.put("amount", amount.longValue());                            //提现金额，单位：分
            signParams.put("bankAccountNo", accNo);                                    //银行卡卡号，3DES加密
            signParams.put("bankAccountName", accName);                                //银行卡户名
            signParams.put("bankName", bankName);                                    //银行名称
            signParams.put("bankSubName", bankName);                                //银行支行名称
            signParams.put("bankChannelNo", bankNo);                                //银行联行号
            String sign = SignUtil.signByMap(key, signParams);
            signParams.put("sign", sign);                                            //签名

            JSONObject jsonObj = JSONObject.parseObject(JsonUtil.objectToJson(signParams));
            jsonObj.put("bankAccountNo", accNoEncryp);
            Response response = HttpUtil.sendPost(url.concat("trans/withdraw"), jsonObj.toString());
            String resultStr = response.body().string();
            log.info(channelName.concat("代付提交原文[{}], 渠道响应[{}]"), jsonObj.toString(), resultStr);

            if (StringUtils.isBlank(resultStr)) {
                status = "1";
                resultCode = "response is null";
                resultMsg = "*代付渠道未响应";
            } else {

                JSONObject resultJson = null;
                try {
                    resultJson = JSONObject.parseObject(resultStr);
                } catch (Exception e) {
                    log.error(channelName.concat("代付[{}]渠道响应错误的JSON报文格式[{}]"), order.toJsonString(), resultStr);
                    status = "1";
                    resultCode = "real error";
                    resultMsg = "*代付出现错误,渠道响应报文格式异常";
                }

                if (resultJson != null) {
                    String code = StringUtils.defaultString(resultJson.getString("code"));
                    String msg = StringUtils.defaultString(resultJson.getString("message"));

                    if ("000000".equals(code)) {
                        status = "1";
                    } else {
                        status = "2";
                    }
                    resultCode = code;
                    resultMsg = msg.length() > 100 ? msg.substring(0, 100) : msg;
                }
            }
        } catch (Exception e) {
            log.error(channelName.concat("代付[{}]执行出现异常:{}"), order.toJsonString(), e.getMessage());
            status = "1";
            resultCode = "submit transfer error";
            resultMsg = "*提交代付出现错误";
        }

        order.setStatus(status);
        order.setSubResultCode(resultCode);
        order.setSubResultMsg(resultMsg);
        order.setBak1(token);
        order.setSubOrderNo(orderNo);
        order.setAcqOrderNo(acqOrderNo);
        log.info(channelName.concat("代付[{}]执行结束"), order.toJsonString());
    }

    @Override
    public void queryTransferStatus(TransferOrder order) {
        log.info(channelName.concat("同步代付状态[{}]执行开始"), order.toJsonString());
        String status = "";
        String resultCode = "";
        String resultMsg = "";
        String orderNo = "";
        String acqOrderNo = "";

        try {
            orderNo = order.getSubOrderNo();
            TransferChannelInfo channelInfo = (TransferChannelInfo) TransferChannelCache.getChannel(order.getOutPayBank() + order.getOutAccNo());

            BigDecimal amount = order.getAmount();
            amount = amount.multiply(oneHundred);

            String outAccNo = order.getOutAccNo();
            String key = channelInfo.getEncryptionKey();
            String url = channelInfo.getPayUrl();


            CommonResult result = entryCardConfirm(orderNo, outAccNo, key, url);
            if (result.getStatus() == 2) {
                order.setStatus("6");
                order.setSubResultCode("Token is null");
                order.setSubResultMsg(result.getMsg());
                return;
            }

            String token = result.getMsg();
            String zqMerNo = order.getAcqMerNo();
            order.setBak2("查询token:" + token);
            TreeMap<String, Object> signParams = new TreeMap<String, Object>();
            signParams.put("token", token);                                            //令牌，明文令牌
            signParams.put("spCode", outAccNo);                                        //服务商编号
            signParams.put("reqFlowNo", orderNo);                                    //请求流水号
            signParams.put("merchantCode", zqMerNo);                                //商户号
            String sign = SignUtil.signByMap(key, signParams);
            signParams.put("sign", sign);

            JSONObject jsonObj = JSONObject.parseObject(JsonUtil.objectToJson(signParams));
            Response response = HttpUtil.sendPost(url.concat("trans/withdrawQuery"), jsonObj.toString());
            String resultStr = response.body().string();
            log.info(channelName.concat("同步代付状态[{}], 渠道响应[{}]"), jsonObj.toString(), resultStr);

            if (StringUtils.isBlank(resultStr)) {
                status = "6";
                resultCode = "response is null";
                resultMsg = "*同步代付状态渠道未响应";
            } else {

                JSONObject resultJson = null;
                try {
                    resultJson = JSONObject.parseObject(resultStr);
                } catch (Exception e) {
                    log.error(channelName.concat("代付[{}]渠道响应错误的JSON报文格式[{}]"), order.toJsonString(), resultStr);
                    status = "6";
                    resultCode = "real error";
                    resultMsg = "*同步代付状态出现错误,渠道响应报文格式异常";
                }

                if (resultJson != null && !resultJson.isEmpty()) {
                    String code = StringUtils.defaultString(resultJson.getString("code"));
                    String msg = StringUtils.defaultString(resultJson.getString("message"));
                    if ("000000".equals(code)) {
                        String data = StringUtils.defaultString(resultJson.getString("data"));
                        JSONObject dataJson = JSONObject.parseObject(data);
                        String remitStatus = StringUtils.defaultString(dataJson.getString("remitStatus"));
                        if ("1".equals(remitStatus)) {
                            status = "4";
                        } else if ("3".equals(remitStatus)) {
                            status = "5";
                        } else {
                            status = "6";
                        }
                        acqOrderNo = StringUtils.defaultString(dataJson.getString("reqFlowNo"));
                        resultCode = remitStatus;
                    } else {
                        status = "6";
                        resultCode = code;
                        resultMsg = msg;
                    }
                }
            }
        } catch (Exception e) {
            log.error(channelName.concat("代付[{}]执行出现异常:{}"), order.toJsonString(), e.getMessage());
            status = "6";
            resultCode = "submit transfer error";
            resultMsg = "同步代付状态出现错误";
        }

        order.setStatus(status);
        order.setResultCode(resultCode);
        order.setResultMsg(resultMsg);
        order.setAcqOrderNo(acqOrderNo);
        log.info(channelName.concat("同步代付状态[{}]执行结束"), order.toJsonString());
    }


    /**
     * 获取令牌
     *
     * @param orderNo 订单编号
     * @param cpCode  出款账户
     * @param key     加密密钥
     * @param url     请求地址
     * @return
     */
    private synchronized CommonResult entryCardConfirm(String orderNo, String cpCode, String key, String url) {
        log.info(channelName.concat("订单号[{}] 获取令牌开始执行"), orderNo);
        CommonResult result = new CommonResult();
        TreeMap<String, Object> sendMap = new TreeMap<>();
        sendMap.put("spCode", cpCode);

        try {
            JSONObject jsonObj = new JSONObject();
            jsonObj.put("spCode", cpCode);
            jsonObj.put("sign", SignUtil.signByMap(key, sendMap));

            String tokenJsonReq = jsonObj.toJSONString();
            Response response = HttpUtil.sendPost(url.concat("base/getQkSpToken"), tokenJsonReq);
            String resultStr = response.body().string();
            log.info(channelName.concat("订单号[{}] 获取令牌请求原文[{}], 渠道响应[{}]"), orderNo, sendMap.toString(), resultStr);
            if (StringUtils.isBlank(resultStr)) {
                result.setStatus(2);
                result.setMsg("*代付获取令牌渠道响应未响应");
                return result;
            } else {

                JSONObject resultJson = null;
                try {
                    resultJson = JSONObject.parseObject(resultStr);
                } catch (Exception e) {
                    log.error(channelName.concat("订单号[{}] [获取令牌] 渠道响应错误的JSON报文格式[{}]"), orderNo, resultStr);
                    result.setStatus(2);
                    result.setMsg("*代付获取令牌渠道响应报文格式错误");
                    return result;
                }

                String code = StringUtils.defaultString(resultJson.getString("code"));
                String msg = StringUtils.defaultString(resultJson.getString("message"));

                if ("000000".equals(code)) {
                    String date = StringUtils.defaultString(resultJson.getString("data"));
                    JSONObject jsonObject = JSONObject.parseObject(date);
                    String token = jsonObject.getString("token");
                    String tokenClearText = EncryptUtil.desDecrypt(token, key);// 解密令牌

                    result.setStatus(1);
                    result.setMsg(tokenClearText);
                    return result;
                } else {
                    result.setStatus(2);
                    result.setMsg(code + ":" + msg);
                    return result;
                }
            }
        } catch (Exception e) {
            log.error(channelName.concat("订单号[{}]获取令牌出现异常:{}"), orderNo, e.getMessage());
            result.setStatus(2);
            result.setMsg("*获取令牌出现错误");
            return result;
        }
    }

}
